package cn.madis.ymcc.service.impl;

import cn.madis.exception.GlobalException;
import cn.madis.ymcc.domain.PayFlow;
import cn.madis.ymcc.domain.PayOrder;
import cn.madis.ymcc.dto.PayNotifyDto;
import cn.madis.ymcc.dto.AlipayNotifyDto;
import cn.madis.ymcc.service.IPayFlowService;
import cn.madis.ymcc.service.IPayNotifyService;
import cn.madis.ymcc.service.IPayOrderService;
import cn.madis.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class PayNotifyServiceImpl implements IPayNotifyService {
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IPayFlowService payFlowService;

    /**
     * 支付宝最大努力通知
     * @param dto
     * @return
     */
    @Override
    public String notify(AlipayNotifyDto dto) {
        //1判断交易状态
        AssertUtil.isTrue(dto.isTradeSuccess(),"交易没有成功");
        Map map = JSONObject.parseObject(JSON.toJSONString(dto), Map.class);
        //2验证签名
        try {
            Boolean aBoolean = Factory.Payment.Common().verifyNotify(map);
            if (!aBoolean) {
                return "SUCCESS";//有问题不要再通知我了
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "ERROR";//再通知我
        }
        //3业务校验 订单对不对 钱对不对
        PayOrder payOrder = payOrderService.checkPayOrder(dto.getOut_trade_no());
        if (payOrder == null){
            return "SUCCESS";//有问题不要再通知我了
        }
        int i = new BigDecimal(dto.getTotal_amount()).compareTo(payOrder.getAmount());
        if (i != 0){
            return "SUCCESS";//有问题不要再通知我了
        }

        Date now = new Date();
        //订单状态校验 状态不对退款
        boolean b = payOrder.getPayStatus() == PayOrder.STATE_UNPAID;
        if (!b){
            try {
                AlipayTradeRefundResponse refund = Factory.Payment.Common().refund(payOrder.getOrderNo(), payOrder.getAmount().toString());
            } catch (Exception e) {
                e.printStackTrace();
                //人工介入
            }
            return "SUCCESS";//有问题不要再通知我了
        }
        //4修改订单状态
        payOrder.setPayStatus(PayOrder.STATE_ACCOMPLISH);
        payOrder.setUpdateTime(now);
        //5记录交易流水
        PayFlow payFlow = new PayFlow();
        payFlow.setNotifyTime(now);
        payFlow.setSubject(dto.getSubject());
        payFlow.setOutTradeNo(dto.getOut_trade_no());
        payFlow.setTotalAmount(new BigDecimal(dto.getTotal_amount()));
        payFlow.setTradeStatus(dto.getTrade_status());
        payFlow.setCode(dto.getCode());
        payFlow.setMsg(dto.getMsg());
        payFlow.setPassbackParams(dto.getPassback_params());
        payFlow.setPaySuccess(dto.isTradeSuccess());


        Map<String, Object> mapTmp  = new HashMap<>();
        mapTmp.put("payOrder",payOrder);
        mapTmp.put("payFlow",payFlow);

        PayNotifyDto payNotifyDto = new PayNotifyDto(
                payOrder.getOrderNo(),
                payOrder.getExtParams()
        );
        //6发起事务mq
        //6.1处理订单服务
        //6.2处理课程购买记录
        Message<String> build = MessageBuilder.withPayload(JSONObject.toJSONString(payNotifyDto)).build();
        //String txProducerGroup, String destination,
        // Message<?> message, Object arg


        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(
                "TxPayOrderCourseGroup",
                "paynotify-topic:alipay-tags",
                build,//检查本地事务参数//消费者方用到的参数
                mapTmp//Object arg执行本地事务参数
        );

        //执行本地事务的状态
        log.info("发送事务消息开始");
        LocalTransactionState localTransactionState = sendResult.getLocalTransactionState();
        //发送消息状态
        SendStatus sendStatus = sendResult.getSendStatus();
        log.info("发送事务消息完成");

        if( localTransactionState != LocalTransactionState.COMMIT_MESSAGE || sendStatus != SendStatus.SEND_OK ){
            throw new GlobalException("下单失败请重新下单");
        }

        return "SUCCESS";
    }


    /**
     * 添加payFlow，修改payOrder
     * @param payOrder
     * @param payFlow
     */
    @Override
    public void savapayFlowUpDate(PayOrder payOrder, PayFlow payFlow) {
        PayOrder payOrderTmp = payOrderService.selectById(payOrder.getId());
        boolean b = payOrderTmp.getPayStatus() == PayOrder.STATE_UNPAID;
        AssertUtil.isTrue(b,"异常");
        payFlowService.insert(payFlow);
        payOrderService.updateById(payOrder);
    }

    /**
     * 检查本地事务
     * @param orderNo
     * @return
     */
    @Override
    public PayOrder selectByPayOrder(String orderNo) {
        EntityWrapper<PayOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no",orderNo);
        return payOrderService.selectOne(wrapper);

    }
}
